import 'package:flutter/material.dart';

import '../entity/candle_entity.dart';
import '../k_chart_widget.dart' show MainState;
import 'base_chart_renderer.dart';

class MainRenderer extends BaseChartRenderer<CandleEntity> {
  late double mCandleWidth;

  late double mCandleLineWidth;

  MainState state;
  bool isLine;
  bool isCustomKChart;
  double _contentPadding = 12.0;

  MainRenderer({
    required Rect mainRect,
    required double maxValue,
    required double minValue,
    required double topPadding,
    required this.state,
    required this.isLine,
    required double scaleX,
    required ChartStyle chartStyle,
    required ChartColors chartColors,
    required this.isCustomKChart,
  }) : super(
          chartRect: mainRect,
          maxValue: maxValue,
          minValue: minValue,
          topPadding: topPadding,
          scaleX: scaleX,
          chartColors: chartColors,
          chartStyle: chartStyle,
        ) {
    mCandleWidth = chartStyle.candleWidth!;
    mCandleLineWidth = chartStyle.candleLineWidth!;
    var diff = maxValue - minValue;
    //计算差
    var newScaleY = (chartRect.height - _contentPadding) / diff;
    //内容区域高度/差=新的比例
    var newDiff = chartRect.height / newScaleY; //高/新比例=新的差
    var value = (newDiff - diff) / 2; //新差-差/2=y轴需要扩大的值
    if (newDiff > diff) {
      this.scaleY = newScaleY;
      this.maxValue += value;
      this.minValue -= value;
    }
  }

  @override
  void drawText(Canvas canvas, CandleEntity data, double x) {
    if (isLine == true) return;
    TextSpan? span;
    if (state == MainState.MA) {
      span = TextSpan(
        children: [
          // if (data.MA5Price != 0)
          //   TextSpan(
          //       text: "MA5:${format(data.MA5Price)}    ",
          //       style: getTextStyle(chartColors.ma5Color!)),
          // if (data.MA9Price != 0)
          //   TextSpan(
          //       text: "MA9:${format(data.MA9Price)}    ",
          //       style: getTextStyle(chartColors.ma9Color!)),
          // if (data.MA20Price != 0)
          //   TextSpan(
          //       text: "MA20:${format(data.MA20Price)}    ",
          //       style: getTextStyle(chartColors.ma20Color!)),
        ],
      );
    } else if (state == MainState.BOLL) {
      span = TextSpan(
        children: [
          if (data.mb != 0)
            TextSpan(
                text: "BOLL:${format(data.mb)}    ",
                style: getTextStyle(chartColors.ma5Color!)),
          if (data.up != 0)
            TextSpan(
                text: "UP:${format(data.up)}    ",
                style: getTextStyle(chartColors.ma9Color!)),
          if (data.dn != 0)
            TextSpan(
                text: "LB:${format(data.dn)}    ",
                style: getTextStyle(chartColors.ma20Color!)),
        ],
      );
    }
    if (span == null) return;
    TextPainter tp = TextPainter(text: span, textDirection: TextDirection.ltr);
    tp.layout();
    tp.paint(canvas, Offset(x, chartRect.top - topPadding));
  }

  @override
  void drawChart(CandleEntity lastPoint, CandleEntity curPoint, double lastX,
      double curX, Size size, Canvas canvas) {
    if (isLine != true) drawCandle(lastPoint, curPoint, canvas, curX);
    if (isLine == true) {
      draLine(lastPoint.close, curPoint.close, canvas, lastX, curX);
    } else if (state == MainState.MA) {
      drawMaLine(lastPoint, curPoint, canvas, lastX, curX);
    } else if (state == MainState.BOLL) {
      drawBollLine(lastPoint, curPoint, canvas, lastX, curX);
    }
  }

  Shader? mLineFillShader;
  late Path mLinePath, mLineFillPath;
  final double mLineStrokeWidth = 1.0;

  Paint get mLinePaint {
    var paint = Paint();
    paint
      ..isAntiAlias = true
      ..style = PaintingStyle.stroke
      ..color = chartColors.kLineColor ?? paint.color;
    return paint;
  }

  final Paint mLineFillPaint = Paint()
    ..style = PaintingStyle.fill
    ..isAntiAlias = true;

  //画折线图
  draLine(double lastPrice, double curPrice, Canvas canvas, double lastX,
      double curX) {
//    drawLine(lastPrice + 100, curPrice + 100, canvas, lastX, curX, chartColors.kLineColor);
    mLinePath /*??*/ = Path();

//    if (lastX == curX) {
//      mLinePath.moveTo(lastX, getY(lastPrice));
//    } else {
////      mLinePath.lineTo(curX, getY(curPrice));
//      mLinePath.cubicTo(
//          (lastX + curX) / 2, getY(lastPrice), (lastX + curX) / 2, getY(curPrice), curX, getY(curPrice));
//    }
    if (lastX == curX) lastX = 0; //起点位置填充
    mLinePath.moveTo(lastX, getY(lastPrice));
    mLinePath.cubicTo((lastX + curX) / 2, getY(lastPrice), (lastX + curX) / 2,
        getY(curPrice), curX, getY(curPrice));

//    //画阴影
    mLineFillShader ??= LinearGradient(
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter,
      tileMode: TileMode.clamp,
      colors: chartColors.kLineShadowColor ?? [],
    ).createShader(Rect.fromLTRB(
        chartRect.left, chartRect.top, chartRect.right, chartRect.bottom));
    mLineFillPaint..shader = mLineFillShader;

    mLineFillPath /*??*/ = Path();

    mLineFillPath.moveTo(lastX, chartRect.height + chartRect.top);
    mLineFillPath.lineTo(lastX, getY(lastPrice));
    mLineFillPath.cubicTo((lastX + curX) / 2, getY(lastPrice),
        (lastX + curX) / 2, getY(curPrice), curX, getY(curPrice));
    mLineFillPath.lineTo(curX, chartRect.height + chartRect.top);
    mLineFillPath.close();

    canvas.drawPath(mLineFillPath, mLineFillPaint);
    mLineFillPath.reset();

    canvas.drawPath(mLinePath,
        mLinePaint..strokeWidth = (mLineStrokeWidth / scaleX).clamp(0.3, 1.0));
    mLinePath.reset();
  }

  void drawMaLine(CandleEntity lastPoint, CandleEntity curPoint, Canvas canvas,
      double lastX, double curX) {
    // if (lastPoint.MA5Price != 0) {
    //   drawLine(lastPoint.MA5Price, curPoint.MA5Price, canvas, lastX, curX,
    //       chartColors.ma5Color!);
    // }
    if (lastPoint.MA9Price != 0) {
      drawLine(lastPoint.MA9Price, curPoint.MA9Price, canvas, lastX, curX,
          chartColors.ma9Color!);
    }
    if (lastPoint.MA20Price != 0) {
      drawLine(lastPoint.MA20Price, curPoint.MA20Price, canvas, lastX, curX,
          chartColors.ma20Color!);
    }
  }

  void drawBollLine(CandleEntity lastPoint, CandleEntity curPoint,
      Canvas canvas, double lastX, double curX) {
    if (lastPoint.up != 0) {
      drawLine(lastPoint.up, curPoint.up, canvas, lastX, curX,
          chartColors.ma9Color!);
    }
    if (lastPoint.mb != 0) {
      drawLine(lastPoint.mb, curPoint.mb, canvas, lastX, curX,
          chartColors.ma5Color!);
    }
    if (lastPoint.dn != 0) {
      drawLine(lastPoint.dn, curPoint.dn, canvas, lastX, curX,
          chartColors.ma20Color!);
    }
  }

  void drawCandle(CandleEntity lastPoint, CandleEntity curPoint, Canvas canvas,
      double curX) {
    var high = getY(curPoint.high);
    var low = getY(curPoint.low);
    var open = getY(curPoint.open);
    var close = getY(curPoint.close);
    double r = mCandleWidth / 2;
    double lineR = mCandleLineWidth / 2;
    if (scaleX != 0 && scaleX != null) {
      //保持k线中心的线不缩放
      lineR = lineR / scaleX;
    }
    // var change = curPoint.change ?? (curPoint.close - curPoint.open);
    bool isUp;
    if (isCustomKChart) {
      isUp = curPoint.isUp;
      // if (lastPoint.open < lastPoint.MA5Price &&
      //     lastPoint.open < lastPoint.MA9Price &&
      //     lastPoint.open < lastPoint.MA20Price &&
      //     lastPoint.close > lastPoint.MA5Price &&
      //     lastPoint.close > lastPoint.MA9Price &&
      //     lastPoint.close > lastPoint.MA20Price
      // ) {
      //   isUp = true;
      // }
      //
      // if (lastPoint.open > lastPoint.MA5Price &&
      //     lastPoint.open > lastPoint.MA9Price &&
      //     lastPoint.open > lastPoint.MA20Price &&
      //     lastPoint.close < lastPoint.MA5Price &&
      //     lastPoint.close < lastPoint.MA9Price &&
      //     lastPoint.close < lastPoint.MA20Price
      // ) {
      //   isUp = false;
      // }
    } else {
      isUp = (curPoint.close - curPoint.open) >= 0;
    }

    //防止数据超过边界
    open = open.clamp(0.0, chartRect.bottom);
    close = close.clamp(0.0, chartRect.bottom);
    high = high.clamp(0.0, chartRect.bottom);
    low = low.clamp(0.0, chartRect.bottom);

    final px1 = (1.0 / WidgetsBinding.instance!.window.devicePixelRatio);
    //防止线太细，强制最细1px
    if ((open - close).abs() < px1) {
      if (open > close) {
        open += px1 / 2;
        close -= px1 / 2;
      } else {
        open -= px1 / 2;
        close += px1 / 2;
      }
    }

    //上涨
    if (isUp) {
      chartPaint.color = chartColors.upColor!;
      var rrect = RRect.fromRectAndRadius(
        Rect.fromLTRB(curX - r, close, curX + r, open),
        Radius.circular(chartStyle.candleRadius ?? 0),
      );
      canvas.drawRRect(rrect, chartPaint);
      canvas.drawRect(
          Rect.fromLTRB(curX - lineR, high, curX + lineR, low), chartPaint);
    } else {
      chartPaint.color = chartColors.dnColor!;
      var rrect = RRect.fromRectAndRadius(
        Rect.fromLTRB(curX - r, open, curX + r, close),
        Radius.circular(chartStyle.candleRadius ?? 0),
      );
      canvas.drawRRect(rrect, chartPaint);
      canvas.drawRect(
          Rect.fromLTRB(curX - lineR, high, curX + lineR, low), chartPaint);
    }
  }

  @override
  void drawRightText(canvas, textStyle, int gridRows) {
    double rowSpace = chartRect.height / gridRows;
    for (var i = 0; i <= gridRows; ++i) {
      double position = 0;
      if (i == 0) {
        position = (gridRows - i) * rowSpace - _contentPadding / 2;
      } else if (i == gridRows) {
        position = (gridRows - i) * rowSpace + _contentPadding / 2;
      } else {
        position = (gridRows - i) * rowSpace;
      }
      var value = position / scaleY + minValue;
      TextSpan span = TextSpan(text: "${format(value)}", style: textStyle);
      TextPainter tp =
          TextPainter(text: span, textDirection: TextDirection.ltr);
      tp.layout();
      double y;
      if (i == 0) {
        y = getY(value) - tp.height * 1.5;
      } else if (i == gridRows) {
        y = getY(value) - tp.height / 2;
      } else {
        y = getY(value) - tp.height;
      }
      y -= 4;
      tp.paint(
          canvas,
          Offset(
              chartRect.width -
                  tp.width -
                  (chartStyle.rightTextMarginRight ?? 0.0),
              y));
    }
  }

  @override
  void drawGrid(Canvas canvas, int gridRows, int gridColumns) {
    canvas.drawLine(Offset.zero, Offset(chartRect.width, 0), gridPaint);

//    final int gridRows = 4, gridColumns = 4;
    double rowSpace = chartRect.height / gridRows;
    for (int i = 0; i <= gridRows; i++) {
      canvas.drawLine(Offset(0, rowSpace * i + topPadding),
          Offset(chartRect.width, rowSpace * i + topPadding), gridPaint);
    }
    double columnSpace = chartRect.width / gridColumns;
    for (int i = 0; i <= columnSpace; i++) {
      canvas.drawLine(Offset(columnSpace * i, 0),
          Offset(columnSpace * i, chartRect.bottom), gridPaint);
    }
  }
}
